package com.zhny.iot.sd.sfj.plugin;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.model.DeviceEntity;
import com.zhny.aiot.plugin.model.MessageEntry;
import com.zhny.aiot.plugin.model.MessageType;
import com.zhny.aiot.plugin.model.TaskEntity;
import com.zhny.aiot.plugin.mqtt.MqttDevice;
import com.zhny.iot.sd.sfj.plugin.model.SDFertilizerStoreEntry;
import io.netty.util.internal.StringUtil;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.pf4j.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.function.BiConsumer;

public class SDFertilizerDevice extends MqttDevice<SDConfig> {
    private final Map<String, String> CommandOperations;
    public SDFertilizerDevice(IDeviceFactory<SDConfig> factory, ICenterFacilities centerFacilities, DeviceEntity entity) {
        super (factory, centerFacilities, entity);
        CommandOperations=new ImmutableMap.Builder<String, String>()
                .put ("openPump","{\"type\": \"set_var\", \"payload\": {\"Data_2\": \"1\"}")
                .put ("closePump","{\"type\": \"set_var\", \"payload\": {\"Data_2\": \"0\"}")
                .put ("openFert","{\"type\": \"set_var\", \"payload\": {\"Data_3\": \"1\"}")
                .put ("closeFert","{\"type\": \"set_var\", \"payload\": {\"Data_3\": \"0\"}")
                .build ();
    }

    @Override
    protected String[] getSubscribeTopics() {
        check();
        String sn = this.getConfig ().getSn ();
        return new String[]{
                "data/ptdj/group1/"+sn,
                "data/ptdj/group2/"+sn
        };
    }

    @Override
    protected BiConsumer<String, MqttMessage> getMessageCallback() {
        return (topic,msg)->{
            byte[] buf = msg.getPayload ();
            try {
                String payload = new String(buf,"utf-8");
                logger.info ("主题：{},内容:{}",topic,payload);
                Map<String,String> bodyMap = mapTo (payload, new TypeReference<Map<String, String>> () {
                });
                if(bodyMap != null){
                    SDFertilizerStoreEntry entry = new SDFertilizerStoreEntry ();
                    if(topic.contains ("data/ptdj/group1/")){
                        if(bodyMap.containsKey ("Data_1")) entry.setEc (bodyMap.get ("Data_1"));
                        if(bodyMap.containsKey ("Data_2")) entry.setPh (bodyMap.get ("Data_2"));
                        if(bodyMap.containsKey ("Data_3")) entry.setPressure (bodyMap.get ("Data_3"));
                    }
                    if(topic.contains ("data/ptdj/group2/")){
                        if(bodyMap.containsKey ("Data_1")) {
                            String value = bodyMap.get ("Data_1").equals ("0")?"待机":"自动运行";
                            entry.setStatus (value);
                        }
                        if(bodyMap.containsKey ("Data_4")) {
                            String value = bodyMap.get ("Data_4").equals ("0")?"关闭":"启动";
                            entry.setPumpStatus (value);
                        }
                        if(bodyMap.containsKey ("Data_5")) {
                            String value = bodyMap.get ("Data_5").equals ("0")?"关闭":"启动";
                            entry.setFertilizerPumpStatus (value);
                        }
                    }

                    saveReal (entry);
                    save (entry);

                    MessageEntry msgEntry =MessageUtils.createMessageEntry (this.getId ());
                    msgEntry.setType (MessageType.RESULT);
                    msgEntry.setData (entry);
                    nofity (msgEntry);
                }

            } catch (UnsupportedEncodingException e) {
                logger.error ("消息解码失败！",e);
            }
        };
    }

    @Override
    public MessageEntry onReceiveTask(TaskEntity entity){
        MessageEntry msgEntry = super.onReceiveTask (entity);
        String method = entity.getMethodName ();
        if(StringUtils.isNullOrEmpty (method)){
           msgEntry.setType (MessageType.ERROR);
           msgEntry.setData ("圣大水肥机动作是空的");
           return msgEntry;
        }
        if(!CommandOperations.containsKey (method)){
            msgEntry.setType (MessageType.ERROR);
            msgEntry.setData ("圣大水肥机动作不存在");
            return msgEntry;
        }
        String body = CommandOperations.get (method);
        String sn = this.getConfig ().getSn ();
        try {
            logger.info ("圣大水肥机{}数据推送：{}",this.getDeviceEntity ().getName (),body);
            pushMessage ("cmd/ptdj/group4/"+sn,body);
        }catch (Exception e){
            logger.info ("圣大水肥机MQTT数据推送失败！",e);
            msgEntry.setType (MessageType.ERROR);
            msgEntry.setData ("圣大水肥机MQTT数据推送失败");
            return msgEntry;
        }
        nofity (msgEntry);
        return msgEntry;
    }

    private void check(){
        SDConfig config = this.getConfig ();
        if(config == null)
            throw new NullPointerException ("圣大水肥机配置必填！");
        String sn = config.getSn ();
        String host = config.getHost ();
        String userName = config.getUserName ();
        String passWord = config.getPassWord ();
        String clientId = config.getClientId ();
        if(StringUtils.isNullOrEmpty (sn))
            throw new NullPointerException ("圣大水肥机设备序列号必填");
        if(StringUtils.isNullOrEmpty (host))
            throw new NullPointerException ("圣大水肥机mqtt地址必填");
        if(StringUtils.isNullOrEmpty (userName))
            throw new NullPointerException ("圣大水肥机mqtt账号必填");
        if(StringUtils.isNullOrEmpty (passWord))
            throw new NullPointerException ("圣大水肥机mqtt密码必填");
        if(StringUtils.isNullOrEmpty (clientId))
            throw new NullPointerException ("圣大水肥机mqtt客户端连接号必填");
    }

    private   <T> T mapTo(String body, TypeReference<T> valueTypeRef){
        if(StringUtil.isNullOrEmpty (body))
            return null;
        ObjectMapper mapper=new ObjectMapper ();
        try {
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            T obj=mapper.readValue (body,valueTypeRef);
            return obj;
        } catch (IOException e) {
            return null;
        }
    }
}
